/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "compose_return_impl.h"
#include "objs.h"

namespace xos_http_protocol
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static compose_return_impl::ITEM_DATA xos_item_data;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    compose_return_impl::compose_return_impl()
    {
        init_data();
    }

    compose_return_impl::~compose_return_impl()
    {
        term();
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int compose_return_impl::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int compose_return_impl::init_data()
    {
        int ret = 0;

        m_pCookieList = 0;
        m_pProperty = 0;
        m_pSendList = 0;
        m_pBodyList = 0;

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int compose_return_impl::init()
    {
        int ret = 0;
        return ret;
    }

    int compose_return_impl::term()
    {
        int ret = 0;
        init_data();
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

    int compose_return_impl::set_tag_property( xos_box::i_str_property * pProperty )
    {
        int ret = 0;
        m_pProperty = pProperty;
        return ret;
    }

    int compose_return_impl::set_send_list( xos_box::i_list * pList )
    {
        int ret = 0;
        m_pSendList = pList;
        return ret;
    }

    int compose_return_impl::set_body_list( xos_box::i_list * pList )
    {
        int ret = 0;
        m_pBodyList = pList;
        return ret;
    }

    int compose_return_impl::set_cookie_list( xos_box::i_list * pList )
    {
        int ret = 0;
        m_pCookieList = pList;
        return ret;
    }

    int compose_return_impl::reset()
    {
        int ret = 0;
        init_data();
        return ret;
    }

    // 
    // 返回值定义：
    // 
    // 0  : 成功，数据在m_pSendList中
    // -1 : 失败，没有http ret code.
    // 
    int compose_return_impl::proc()
    {
        int ret = 0;

        xos_box::i_buf * pBuf = mgr::container()->box()->buf();
        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nLen = xos_box::i_buf::BUF_SIZE;
        int nPos = 0;
        xos_box::i_variant * pTagVT = 0;
        const char * lpszTagName = 0;
        xos_box::i_buf * pBodyBuf = 0;
        int nBodyLen = 0;

        // 查找ret code,没有的话就失败
        if( 0 == ret )
        {
            const char *lpszRetCode = m_pProperty->str( HTTP_REQUEST_RET_CODE, 0, 0, 0 );
            if( lpszRetCode )
            {
                int len = mgr::container()->crt()->sprintf( lpszData + nPos, nLen, "HTTP/1.1 %s\r\n", lpszRetCode );
                nPos += len;
                nLen -= len;
                m_pBodyList->reset();
            }
            else
            {
                ret = -1;
            }
        }

        // 得到数据体长度
        while( ( 0 == ret ) && ( pBodyBuf = ( xos_box::i_buf* )m_pBodyList->next() ) )
        {
            nBodyLen += pBodyBuf->get_len( 0 );
        }

        // 加入content length
        if( 0 == ret )
        {
            int len = mgr::container()->crt()->sprintf( lpszData + nPos, nLen, "%s: %d\r\n", HTTP_CONTENT_LENGTH, nBodyLen );
            nPos += len;
            nLen -= len;
        }

        if( 0 == ret )
        {
            xos_box::i_variant * pVT = m_pProperty->remove( HTTP_REQUEST_RET_CODE );
            pVT->release();
            m_pProperty->reset();
        }

        // 加入所有tag
        while( ( 0 == ret ) && ( pTagVT = m_pProperty->next( &lpszTagName, 0, 0, 0 ) ) )
        {
            int len = mgr::container()->crt()->sprintf( lpszData + nPos, nLen, "%s: %s\r\n", lpszTagName, pTagVT->str( 0, 0, 0 ) );
            nPos += len;
            nLen -= len;
        }

        if( 0 == ret )
        {
            ret = add_cookie_tags( lpszData, nLen, nPos );
        }

        // 保存http头
        if( 0 == ret )
        {
            int len = mgr::container()->crt()->sprintf( lpszData + nPos, nLen, "\r\n" );
            nPos += len;
            nLen -= len;
            pBuf->set_len( nPos );
            m_pSendList->push_back( pBuf );
            pBuf = 0;
        }

        // 加入包体
        while( ( 0 == ret ) && ( pBodyBuf = ( xos_box::i_buf* )m_pBodyList->front( 0 ) ) )
        {
            // 如果包头能和包体合为一包，就合并
            if( nBodyLen < xos_box::i_buf::BUF_SIZE - nPos )
            {
                m_pSendList->add_data( pBodyBuf, true );
                xos_stl::release_interface( pBodyBuf );
            }
            else
            {
                m_pSendList->push_back( pBodyBuf );
            }
            m_pBodyList->pop_front();
        }

        xos_stl::release_interface( pBuf );

        return ret;
    }

    int compose_return_impl::add_cookie_tags( char * pBuf, int & nLen, int & nPos )
    {
        int ret = 0;

        xos::i_crt * pCrt = mgr::container()->crt();
        xos_box::i_list * pList = m_pCookieList;
        cookie_impl * pC = 0;

        pList->reset();

        while( ( pC = ( cookie_impl * )pList->next() ) )
        {
            pC->serial();
            int len = pCrt->sprintf( pBuf + nPos, nLen, "%s: %s\r\n", xos_http_protocol::HTTP_SET_COOKIE, pC->m_cookie.c_str() );
            nPos += len;
            nLen -= len;
        }

        return ret;
    }

} // xos_http_protocol
